#pragma once 

#include<iostream>
#include<vector>
#include<semaphore.h>
#include<pthread.h>

#define NUM 32

template<class T>
class RingQueue
{
  private:
    std::vector<T> q;
    int cap;
    int c_pos;
    int p_pos;

    sem_t blank_sem;
    sem_t date_sem;
  private:
    void P(sem_t& s)
    {
      sem_wait(&s);
    }
    void V(sem_t& s)
    {
      sem_post(&s);
    }
  public:
    RingQueue(int _cap=NUM):cap(_cap)
    {
      q.resize(cap);
      sem_init(&blank_sem,0,cap);
      sem_init(&date_sem,0,0);
    }

    //生产者调用，生产数据，关心blank
    void Push(const T& in) 
    {
      P(blank_sem);
      q[p_pos]=in;
      V(date_sem);

      p_pos++;
      p_pos%=cap;
    }

    //消费者调用，消费数据，关心date资源
    void Pop(T& out)
    {
      P(date_sem);
      out=q[c_pos];
      V(blank_sem);

      c_pos++;
      c_pos%=cap;
    }

    ~RingQueue()
    {
      sem_destroy(&blank_sem);
      sem_destroy(&date_sem);
    }
};
